package co.edu.unal.cg.splines.interact;

import java.util.ArrayList;

import processing.core.PApplet;
import processing.core.PVector;
import remixlab.proscene.InteractiveFrame;
import remixlab.proscene.Scene;
import co.edu.unal.cg.splines.HermiteSpline;

public class InteractiveHermiteSpline implements InteractiveSpline{

	HermiteSpline spline;
	Scene scene;

	ArrayList<HermiteSplineControlPoint> controlPoints = new ArrayList<HermiteSplineControlPoint>();
	
	
	public InteractiveHermiteSpline(Scene scene){
		this.scene = scene;
		this.spline = new HermiteSpline(0.1);
		
	}
	
	public void addControlPoint(PVector position) {
		addControlPoint(position, new PVector(1, 1, 1));
	}

	public void addControlPoint(PVector position, PVector direction) {
		controlPoints.add(new HermiteSplineControlPoint(position, direction,
				scene, spline));
	}

	public void draw(PApplet canvas) {
		for(HermiteSplineControlPoint controlPoint : controlPoints){
			controlPoint.draw(canvas);
		}
		this.spline.draw(canvas);
	}

	private class HermiteSplineControlPoint {

		private final float r = 1;
		
		private final float w = 1;
		private final float d = 1;
		private final float h = 1;

		InteractiveFrame positionFrame;
		InteractiveFrame directionFrame;
		HermiteSpline.ControlPoint referenceControlPoint;

		public HermiteSplineControlPoint(PVector position, PVector direction,
				Scene scene, HermiteSpline parentSpline) {

			this.positionFrame = new InteractiveFrame(scene);
			this.positionFrame.setPosition(position);

			this.directionFrame = new InteractiveFrame(scene);
			this.directionFrame.setPosition(PVector.add(position, direction));
			this.directionFrame.setReferenceFrame(positionFrame);

			this.referenceControlPoint = new HermiteSpline.ControlPoint(
					position, new PVector(1, 1, 1));

			spline.addControlPoint(referenceControlPoint);

		}

		public void draw(PApplet canvas) {
			canvas.pushMatrix();
			canvas.pushStyle();
			this.drawShape(canvas);
			updateReferenceControlPoint();
			canvas.popStyle();
			canvas.popMatrix();
		}

		private void drawShape(PApplet canvas) {
			int gradientColor = 0xAA000000;
			canvas.pushStyle();
			canvas.stroke(gradientColor);
			PVector p1 = positionFrame.position();
			PVector p2 = directionFrame.position();
			canvas.line(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
			
			positionFrame.applyTransformation(); 
			canvas.noStroke();
			if (positionFrame.grabsMouse())
				canvas.fill(255, 0, 0);
			else
				canvas.fill(this.getColor());
			canvas.sphere(r);

			
			
			canvas.pushMatrix();
			directionFrame.applyTransformation();
			if (directionFrame.grabsMouse())
				canvas.fill(255, 0, 0);
			else
				canvas.fill(gradientColor);
			
			canvas.box(w, h, d);
			canvas.popMatrix();
			canvas.popStyle();
		}

		private int getColor() {
			return 100;
		}

		private void updateReferenceControlPoint() {
			PVector pos = this.positionFrame.position();
			this.referenceControlPoint.coordinates.x = pos.x;
			this.referenceControlPoint.coordinates.y = pos.y;
			this.referenceControlPoint.coordinates.z = pos.z;
			
			PVector dir = PVector.sub(this.directionFrame.position(),pos);
			this.referenceControlPoint.orientation.x = dir.x;
			this.referenceControlPoint.orientation.y = dir.y;
			this.referenceControlPoint.orientation.z = dir.z;
		}

	}

}
